package mc.support.orm.shard.sql;

import com.alibaba.druid.sql.ast.*;
import com.alibaba.druid.sql.ast.expr.*;
import com.alibaba.druid.sql.ast.statement.*;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
import mc.support.orm.shard.ShardStrategy;
import mc.support.orm.shard.sql.comm.AbstractSqlPhaser;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Created with IntelliJ IDEA. <br/>
 * Author: Francis Yuen    <br/>
 * Date: 2014-10-15  <br/>
 */
public class SelectSqlPhaser extends AbstractSqlPhaser {

    @Override
    protected SQLStatement doPhase( SQLStatement statement, Object params, String mapperId, ShardStrategy strategy ) {
        SQLSelectStatement select = (SQLSelectStatement) statement;
        statement.accept( new TableNameModifier0( strategy, params, mapperId ) );
        return select;
    }

    private class TableNameModifier0 implements SQLASTVisitor {

        private final ShardStrategy strategy;
        private final Object params;
        private final String mapperId;
        private Set<SQLExprTableSource> modified;

        public TableNameModifier0( ShardStrategy strategy, Object params, String mapperId ) {
            this.strategy = strategy;
            this.params = params;
            this.mapperId = mapperId;
        }

        @Override
        public void endVisit( SQLAllColumnExpr x ) {
        }

        @Override
        public void endVisit( SQLBetweenExpr x ) {
            x.beginExpr.accept( this );
            x.endExpr.accept( this );
        }

        @Override
        public void endVisit( SQLBinaryOpExpr x ) {
            x.getLeft().accept( this );
            x.getRight().accept( this );
        }

        @Override
        public void endVisit( SQLCaseExpr x ) {
            x.getElseExpr().accept( this );

        }

        @Override
        public void endVisit( SQLCaseExpr.Item x ) {
            x.getConditionExpr().accept( this );
            x.getValueExpr().accept( this );
        }

        @Override
        public void endVisit( SQLCharExpr x ) {
        }

        @Override
        public void endVisit( SQLIdentifierExpr x ) {
        }

        @Override
        public void endVisit( SQLInListExpr x ) {
            List<SQLExpr> exprList = x.getTargetList();
            for ( SQLExpr expr : exprList ) {
                expr.accept( this );
            }
        }

        @Override
        public void endVisit( SQLIntegerExpr x ) {
        }

        @Override
        public void endVisit( SQLExistsExpr x ) {
            x.getSubQuery().accept( this );
        }

        @Override
        public void endVisit( SQLNCharExpr x ) {
        }

        @Override
        public void endVisit( SQLNotExpr x ) {
            x.getExpr().accept( this );
        }

        @Override
        public void endVisit( SQLNullExpr x ) {
        }

        @Override
        public void endVisit( SQLNumberExpr x ) {
        }

        @Override
        public void endVisit( SQLPropertyExpr x ) {
            x.getOwner().accept( this );
        }

        @Override
        public void endVisit( SQLSelectGroupByClause x ) {
            if( x.getHaving() != null  ){
                x.getHaving().accept( this );
            }
            List<SQLExpr> items = x.getItems();
            for ( SQLExpr expr : items ) {
                expr.accept( this );
            }
        }

        @Override
        public void endVisit( SQLSelectItem x ) {
            x.getExpr().accept( this );
        }

        @Override
        public void endVisit( SQLSelectStatement selectStatement ) {
            selectStatement.getSelect().accept( this );
        }

        @Override
        public void postVisit( SQLObject astNode ) {
        }

        @Override
        public void preVisit( SQLObject astNode ) {

        }

        @Override
        public boolean visit( SQLAllColumnExpr x ) {
            return false;
        }

        @Override
        public boolean visit( SQLBetweenExpr x ) {
            return true;
        }

        @Override
        public boolean visit( SQLBinaryOpExpr x ) {
            return true;
        }

        @Override
        public boolean visit( SQLCaseExpr x ) {
            return true;
        }

        @Override
        public boolean visit( SQLCaseExpr.Item x ) {
            return true;
        }

        @Override
        public boolean visit( SQLCastExpr x ) {
            return true;
        }

        @Override
        public boolean visit( SQLCharExpr x ) {
            return false;
        }

        @Override
        public boolean visit( SQLExistsExpr x ) {
            return true;
        }

        @Override
        public boolean visit( SQLIdentifierExpr x ) {
            return true;
        }

        @Override
        public boolean visit( SQLInListExpr x ) {
            return true;
        }

        @Override
        public boolean visit( SQLIntegerExpr x ) {
            return false;
        }

        @Override
        public boolean visit( SQLNCharExpr x ) {
            return false;
        }

        @Override
        public boolean visit( SQLNotExpr x ) {
            return false;
        }

        @Override
        public boolean visit( SQLNullExpr x ) {
            return false;
        }

        @Override
        public boolean visit( SQLNumberExpr x ) {
            return false;
        }

        @Override
        public boolean visit( SQLPropertyExpr x ) {
            return true;
        }

        @Override
        public boolean visit( SQLSelectGroupByClause x ) {
            return true;
        }

        @Override
        public boolean visit( SQLSelectItem x ) {
            return true;
        }

        @Override
        public void endVisit( SQLCastExpr x ) {
            x.getExpr().accept( this );
        }

        @Override
        public boolean visit( SQLSelectStatement astNode ) {
            return true;
        }

        @Override
        public void endVisit( SQLAggregateExpr astNode ) {
        }

        @Override
        public boolean visit( SQLAggregateExpr astNode ) {
            return false;
        }

        @Override
        public boolean visit( SQLVariantRefExpr x ) {
            return false;
        }

        @Override
        public void endVisit( SQLVariantRefExpr x ) {
        }

        @Override
        public boolean visit( SQLQueryExpr x ) {
            return true;
        }

        @Override
        public void endVisit( SQLQueryExpr x ) {
            x.getSubQuery().accept( this );
        }

        @Override
        public boolean visit( SQLUnaryExpr x ) {
            return true;
        }

        @Override
        public void endVisit( SQLUnaryExpr x ) {
            x.getExpr().accept( this );
        }

        @Override
        public boolean visit( SQLHexExpr x ) {
            return false;
        }

        @Override
        public void endVisit( SQLHexExpr x ) {
        }

        @Override
        public boolean visit( SQLSelect x ) {
            return true;
        }

        @Override
        public void endVisit( SQLSelect select ) {
            select.getQuery().accept( this );
        }

        @Override
        public boolean visit( SQLSelectQueryBlock x ) {
            return true;
        }

        @Override
        public void endVisit( SQLSelectQueryBlock x ) {
            x.getFrom().accept( this );
            List<SQLSelectItem> items = x.getSelectList();
            for ( SQLSelectItem item : items ) {
                item.getExpr().accept( this );
            }
        }

        @Override
        public boolean visit( SQLExprTableSource x ) {
            return true;
        }

        @Override
        public void endVisit( SQLExprTableSource tableSource ) {
            if ( null != modified && modified.contains( tableSource ) ) return;
            SQLExpr expr = tableSource.getExpr();
            if ( expr instanceof SQLIdentifierExpr ) {
                SQLIdentifierExpr oldExpr = (SQLIdentifierExpr) tableSource.getExpr();
                String newName = strategy.shardTableName( oldExpr.getSimleName(), params, mapperId );
                tableSource.setExpr( new SQLIdentifierExpr( newName ) );
                if ( null == modified ) modified = new HashSet<>();
                modified.add( tableSource );
            }
        }

        @Override
        public boolean visit( SQLOrderBy x ) {
            return true;
        }

        @Override
        public void endVisit( SQLOrderBy x ) {
            List<SQLSelectOrderByItem> items =  x.getItems();
            for ( SQLSelectOrderByItem item : items ) {
                item.accept( this );
            }
        }

        @Override
        public boolean visit( SQLSelectOrderByItem x ) {
            return true;
        }

        @Override
        public void endVisit( SQLSelectOrderByItem x ) {
            x.getExpr().accept( this );
        }

        @Override
        public boolean visit( SQLDropTableStatement x ) {
            return false;
        }

        @Override
        public void endVisit( SQLDropTableStatement x ) {
        }

        @Override
        public boolean visit( SQLCreateTableStatement x ) {
            return false;
        }

        @Override
        public void endVisit( SQLCreateTableStatement x ) {
        }

        @Override
        public boolean visit( SQLColumnDefinition x ) {
            return true;
        }

        @Override
        public void endVisit( SQLColumnDefinition x ) {
            x.getComment().accept( this );
            x.getDefaultExpr().accept( this );
        }

        @Override
        public boolean visit( SQLDataType x ) {
            return true;
        }

        @Override
        public void endVisit( SQLDataType x ) {
            List<SQLExpr> exprs = x.getArguments();
            for ( SQLExpr expr : exprs ) {
                expr.accept( this );
            }
        }

        @Override
        public boolean visit( SQLCharactorDataType x ) {
            return false;
        }

        @Override
        public void endVisit( SQLCharactorDataType x ) {
            List<SQLExpr> exprs = x.getArguments();
            for ( SQLExpr expr : exprs ) {
                expr.accept( this );
            }
        }

        @Override
        public boolean visit( SQLDeleteStatement x ) {
            return true;
        }

        @Override
        public void endVisit( SQLDeleteStatement x ) {
            x.getTableSource().accept( this );
        }

        @Override
        public boolean visit( SQLCurrentOfCursorExpr x ) {
            return false;
        }

        @Override
        public void endVisit( SQLCurrentOfCursorExpr x ) {
        }

        @Override
        public boolean visit( SQLInsertStatement x ) {
            return false;
        }

        @Override
        public void endVisit( SQLInsertStatement x ) {

        }

        @Override
        public boolean visit( SQLInsertStatement.ValuesClause x ) {
            return false;
        }

        @Override
        public void endVisit( SQLInsertStatement.ValuesClause x ) {

        }

        @Override
        public boolean visit( SQLUpdateSetItem x ) {
            return false;
        }

        @Override
        public void endVisit( SQLUpdateSetItem x ) {

        }

        @Override
        public boolean visit( SQLUpdateStatement x ) {
            return false;
        }

        @Override
        public void endVisit( SQLUpdateStatement x ) {

        }

        @Override
        public boolean visit( SQLCreateViewStatement x ) {
            return false;
        }

        @Override
        public void endVisit( SQLCreateViewStatement x ) {

        }

        @Override
        public boolean visit( NotNullConstraint x ) {
            return false;
        }

        @Override
        public void endVisit( NotNullConstraint x ) {

        }

        @Override
        public void endVisit( SQLMethodInvokeExpr x ) {

        }

        @Override
        public boolean visit( SQLMethodInvokeExpr x ) {
            return false;
        }

        @Override
        public void endVisit( SQLUnionQuery x ) {
            x.getLeft().accept( this );
            x.getRight().accept( this );
        }

        @Override
        public boolean visit( SQLUnionQuery x ) {
            return true;
        }

        @Override
        public void endVisit( SQLSetStatement x ) {
        }

        @Override
        public boolean visit( SQLSetStatement x ) {
            return false;
        }

        @Override
        public void endVisit( SQLAssignItem x ) {

        }

        @Override
        public boolean visit( SQLAssignItem x ) {
            return false;
        }

        @Override
        public void endVisit( SQLCallStatement x ) {

        }

        @Override
        public boolean visit( SQLCallStatement x ) {
            return false;
        }

        @Override
        public void endVisit( SQLJoinTableSource x ) {
            x.getCondition().accept( this );
            x.getLeft().accept( this );
            x.getRight().accept( this );
        }

        @Override
        public boolean visit( SQLJoinTableSource x ) {
            return true;
        }

        @Override
        public void endVisit( SQLSomeExpr x ) {

        }

        @Override
        public boolean visit( SQLSomeExpr x ) {
            return false;
        }

        @Override
        public void endVisit( SQLAnyExpr x ) {

        }

        @Override
        public boolean visit( SQLAnyExpr x ) {
            return false;
        }

        @Override
        public void endVisit( SQLAllExpr x ) {

        }

        @Override
        public boolean visit( SQLAllExpr x ) {
            return false;
        }

        @Override
        public void endVisit( SQLInSubQueryExpr x ) {

        }

        @Override
        public boolean visit( SQLInSubQueryExpr x ) {
            return false;
        }

        @Override
        public void endVisit( SQLListExpr x ) {

        }

        @Override
        public boolean visit( SQLListExpr x ) {
            return false;
        }

        @Override
        public void endVisit( SQLSubqueryTableSource x ) {
            x.getSelect().accept( this );
        }

        @Override
        public boolean visit( SQLSubqueryTableSource x ) {
            return true;
        }

        @Override
        public void endVisit( SQLTruncateStatement x ) {

        }

        @Override
        public boolean visit( SQLTruncateStatement x ) {
            return false;
        }

        @Override
        public void endVisit( SQLDefaultExpr x ) {

        }

        @Override
        public boolean visit( SQLDefaultExpr x ) {
            return false;
        }

        @Override
        public void endVisit( SQLCommentStatement x ) {

        }

        @Override
        public boolean visit( SQLCommentStatement x ) {
            return false;
        }

        @Override
        public void endVisit( SQLUseStatement x ) {

        }

        @Override
        public boolean visit( SQLUseStatement x ) {
            return false;
        }

        @Override
        public boolean visit( SQLAlterTableAddColumn x ) {
            return false;
        }

        @Override
        public void endVisit( SQLAlterTableAddColumn x ) {

        }

        @Override
        public boolean visit( SQLAlterTableDropColumnItem x ) {
            return false;
        }

        @Override
        public void endVisit( SQLAlterTableDropColumnItem x ) {

        }

        @Override
        public boolean visit( SQLAlterTableDropIndex x ) {
            return false;
        }

        @Override
        public void endVisit( SQLAlterTableDropIndex x ) {

        }

        @Override
        public boolean visit( SQLDropIndexStatement x ) {
            return false;
        }

        @Override
        public void endVisit( SQLDropIndexStatement x ) {

        }

        @Override
        public boolean visit( SQLDropViewStatement x ) {
            return false;
        }

        @Override
        public void endVisit( SQLDropViewStatement x ) {

        }

        @Override
        public boolean visit( SQLSavePointStatement x ) {
            return false;
        }

        @Override
        public void endVisit( SQLSavePointStatement x ) {

        }

        @Override
        public boolean visit( SQLRollbackStatement x ) {
            return false;
        }

        @Override
        public void endVisit( SQLRollbackStatement x ) {

        }

        @Override
        public boolean visit( SQLReleaseSavePointStatement x ) {
            return false;
        }

        @Override
        public void endVisit( SQLReleaseSavePointStatement x ) {

        }

        @Override
        public void endVisit( SQLCommentHint x ) {

        }

        @Override
        public boolean visit( SQLCommentHint x ) {
            return false;
        }

        @Override
        public void endVisit( SQLCreateDatabaseStatement x ) {

        }

        @Override
        public boolean visit( SQLCreateDatabaseStatement x ) {
            return false;
        }

        @Override
        public void endVisit( SQLOver x ) {

        }

        @Override
        public boolean visit( SQLOver x ) {
            return false;
        }

        @Override
        public void endVisit( SQLColumnPrimaryKey x ) {

        }

        @Override
        public boolean visit( SQLColumnPrimaryKey x ) {
            return false;
        }

        @Override
        public boolean visit( SQLColumnUniqueKey x ) {
            return false;
        }

        @Override
        public void endVisit( SQLColumnUniqueKey x ) {

        }

        @Override
        public void endVisit( SQLWithSubqueryClause x ) {

        }

        @Override
        public boolean visit( SQLWithSubqueryClause x ) {
            return false;
        }

        @Override
        public void endVisit( SQLWithSubqueryClause.Entry x ) {

        }

        @Override
        public boolean visit( SQLWithSubqueryClause.Entry x ) {
            return false;
        }

        @Override
        public void endVisit( SQLAlterTableAlterColumn x ) {

        }

        @Override
        public boolean visit( SQLAlterTableAlterColumn x ) {
            return false;
        }

        @Override
        public boolean visit( SQLCheck x ) {
            return false;
        }

        @Override
        public void endVisit( SQLCheck x ) {

        }

        @Override
        public boolean visit( SQLAlterTableDropForeinKey x ) {
            return false;
        }

        @Override
        public void endVisit( SQLAlterTableDropForeinKey x ) {

        }

        @Override
        public boolean visit( SQLAlterTableDropPrimaryKey x ) {
            return false;
        }

        @Override
        public void endVisit( SQLAlterTableDropPrimaryKey x ) {

        }

        @Override
        public boolean visit( SQLAlterTableDisableKeys x ) {
            return false;
        }

        @Override
        public void endVisit( SQLAlterTableDisableKeys x ) {

        }

        @Override
        public boolean visit( SQLAlterTableEnableKeys x ) {
            return false;
        }

        @Override
        public void endVisit( SQLAlterTableEnableKeys x ) {

        }

        @Override
        public boolean visit( SQLAlterTableStatement x ) {
            return false;
        }

        @Override
        public void endVisit( SQLAlterTableStatement x ) {

        }

        @Override
        public boolean visit( SQLAlterTableDisableConstraint x ) {
            return false;
        }

        @Override
        public void endVisit( SQLAlterTableDisableConstraint x ) {

        }

        @Override
        public boolean visit( SQLAlterTableEnableConstraint x ) {
            return false;
        }

        @Override
        public void endVisit( SQLAlterTableEnableConstraint x ) {

        }

        @Override
        public boolean visit( SQLColumnCheck x ) {
            return false;
        }

        @Override
        public void endVisit( SQLColumnCheck x ) {

        }

        @Override
        public boolean visit( SQLExprHint x ) {
            return false;
        }

        @Override
        public void endVisit( SQLExprHint x ) {

        }

        @Override
        public boolean visit( SQLAlterTableDropConstraint x ) {
            return false;
        }

        @Override
        public void endVisit( SQLAlterTableDropConstraint x ) {

        }

        @Override
        public boolean visit( SQLUnique x ) {
            return false;
        }

        @Override
        public void endVisit( SQLUnique x ) {

        }

        @Override
        public boolean visit( SQLPrimaryKeyImpl x ) {
            return false;
        }

        @Override
        public void endVisit( SQLPrimaryKeyImpl x ) {

        }

        @Override
        public boolean visit( SQLCreateIndexStatement x ) {
            return false;
        }

        @Override
        public void endVisit( SQLCreateIndexStatement x ) {

        }

        @Override
        public boolean visit( SQLAlterTableRenameColumn x ) {
            return false;
        }

        @Override
        public void endVisit( SQLAlterTableRenameColumn x ) {

        }

        @Override
        public boolean visit( SQLColumnReference x ) {
            return false;
        }

        @Override
        public void endVisit( SQLColumnReference x ) {

        }

        @Override
        public boolean visit( SQLForeignKeyImpl x ) {
            return false;
        }

        @Override
        public void endVisit( SQLForeignKeyImpl x ) {

        }

        @Override
        public boolean visit( SQLDropSequenceStatement x ) {
            return false;
        }

        @Override
        public void endVisit( SQLDropSequenceStatement x ) {

        }

        @Override
        public boolean visit( SQLDropTriggerStatement x ) {
            return false;
        }

        @Override
        public void endVisit( SQLDropTriggerStatement x ) {

        }

        @Override
        public void endVisit( SQLDropUserStatement x ) {

        }

        @Override
        public boolean visit( SQLDropUserStatement x ) {
            return false;
        }

        @Override
        public void endVisit( SQLExplainStatement x ) {

        }

        @Override
        public boolean visit( SQLExplainStatement x ) {
            return false;
        }

        @Override
        public void endVisit( SQLGrantStatement x ) {

        }

        @Override
        public boolean visit( SQLGrantStatement x ) {
            return false;
        }

        @Override
        public void endVisit( SQLDropDatabaseStatement x ) {

        }

        @Override
        public boolean visit( SQLDropDatabaseStatement x ) {
            return false;
        }

        @Override
        public void endVisit( SQLAlterTableAddIndex x ) {

        }

        @Override
        public boolean visit( SQLAlterTableAddIndex x ) {
            return false;
        }

        @Override
        public void endVisit( SQLAlterTableAddConstraint x ) {

        }

        @Override
        public boolean visit( SQLAlterTableAddConstraint x ) {
            return false;
        }

        @Override
        public void endVisit( SQLCreateTriggerStatement x ) {

        }

        @Override
        public boolean visit( SQLCreateTriggerStatement x ) {
            return false;
        }

        @Override
        public void endVisit( SQLDropFunctionStatement x ) {

        }

        @Override
        public boolean visit( SQLDropFunctionStatement x ) {
            return false;
        }

        @Override
        public void endVisit( SQLDropTableSpaceStatement x ) {

        }

        @Override
        public boolean visit( SQLDropTableSpaceStatement x ) {
            return false;
        }

        @Override
        public void endVisit( SQLDropProcedureStatement x ) {

        }

        @Override
        public boolean visit( SQLDropProcedureStatement x ) {
            return false;
        }

    }

//    private class TableNameModifier implements SelectVisitor, FromItemVisitor, ExpressionVisitor, ItemsListVisitor {
//
//        private final Object params;
//        private final String mapperId;
//        private final ShardStrategy shardStrategy;
//
//        private TableNameModifier( Object params, String mapperId, ShardStrategy shardStrategy ) {
//            this.params = params;
//            this.mapperId = mapperId;
//            this.shardStrategy = shardStrategy;
//        }
//
//        private String phaseTableName( String originalName ) {
//            return shardStrategy.shardTableName( originalName, params, mapperId );
//        }
//
//        @SuppressWarnings( "unchecked" )
//        public void visit( PlainSelect plainSelect ) {
//            plainSelect.getFromItem().accept( this );
//
//            List<Join> joins = plainSelect.getJoins();
//            if ( null != joins ) {
//                for ( Join join : joins ) {
//                    join.getRightItem().accept( this );
//                }
//            }
//            Expression where = plainSelect.getWhere();
//            if ( null != where ) where.accept( this );
//        }
//
//        @SuppressWarnings( "unchecked" )
//        public void visit( Union union ) {
//            Iterable<PlainSelect> it = union.getPlainSelects();
//            for ( PlainSelect plainSelect : it ) {
//                visit( plainSelect );
//            }
//        }
//
//        public void visit( Table tableName ) {
//            String table = tableName.getName();
//            table = phaseTableName( table );
//            tableName.setName( table );
//        }
//
//        public void visit( SubSelect subSelect ) {
//            subSelect.getSelectBody().accept( this );
//        }
//
//        public void visit( Addition addition ) {
//            visitBinaryExpression( addition );
//        }
//
//        public void visit( AndExpression andExpression ) {
//            visitBinaryExpression( andExpression );
//        }
//
//        public void visit( Between between ) {
//            between.getLeftExpression().accept( this );
//            between.getBetweenExpressionStart().accept( this );
//            between.getBetweenExpressionEnd().accept( this );
//        }
//
//        public void visit( Column tableColumn ) {
//        }
//
//        public void visit( Division division ) {
//            visitBinaryExpression( division );
//        }
//
//        public void visit( DoubleValue doubleValue ) {
//        }
//
//        public void visit( EqualsTo equalsTo ) {
//            visitBinaryExpression( equalsTo );
//        }
//
//        public void visit( Function function ) {
//        }
//
//        public void visit( GreaterThan greaterThan ) {
//            visitBinaryExpression( greaterThan );
//        }
//
//        public void visit( GreaterThanEquals greaterThanEquals ) {
//            visitBinaryExpression( greaterThanEquals );
//        }
//
//        public void visit( InExpression inExpression ) {
//            inExpression.getLeftExpression().accept( this );
//            inExpression.getItemsList().accept( this );
//        }
//
//        public void visit( InverseExpression inverseExpression ) {
//            inverseExpression.getExpression().accept( this );
//        }
//
//        public void visit( IsNullExpression isNullExpression ) {
//        }
//
//        public void visit( JdbcParameter jdbcParameter ) {
//        }
//
//        public void visit( LikeExpression likeExpression ) {
//            visitBinaryExpression( likeExpression );
//        }
//
//        public void visit( ExistsExpression existsExpression ) {
//            existsExpression.getRightExpression().accept( this );
//        }
//
//        public void visit( LongValue longValue ) {
//        }
//
//        public void visit( MinorThan minorThan ) {
//            visitBinaryExpression( minorThan );
//        }
//
//        public void visit( MinorThanEquals minorThanEquals ) {
//            visitBinaryExpression( minorThanEquals );
//        }
//
//        public void visit( Multiplication multiplication ) {
//            visitBinaryExpression( multiplication );
//        }
//
//        public void visit( NotEqualsTo notEqualsTo ) {
//            visitBinaryExpression( notEqualsTo );
//        }
//
//        public void visit( NullValue nullValue ) {
//        }
//
//        public void visit( OrExpression orExpression ) {
//            visitBinaryExpression( orExpression );
//        }
//
//        public void visit( Parenthesis parenthesis ) {
//            parenthesis.getExpression().accept( this );
//        }
//
//        public void visit( Subtraction subtraction ) {
//            visitBinaryExpression( subtraction );
//        }
//
//        public void visitBinaryExpression( BinaryExpression binaryExpression ) {
//            binaryExpression.getLeftExpression().accept( this );
//            binaryExpression.getRightExpression().accept( this );
//        }
//
//        @SuppressWarnings( "unchecked" )
//        public void visit( ExpressionList expressionList ) {
//            for ( Iterator it = expressionList.getExpressions().iterator(); it.hasNext(); ) {
//                Expression expression = (Expression) it.next();
//                expression.accept( this );
//            }
//
//        }
//
//        public void visit( DateValue dateValue ) {
//        }
//
//        public void visit( TimestampValue timestampValue ) {
//        }
//
//        public void visit( TimeValue timeValue ) {
//        }
//
//        /*
//         * (non-Javadoc)
//         *
//         * @see
//         * net.sf.jsqlparser.expression.ExpressionVisitor#visit(net.sf.jsqlparser
//         * .expression.CaseExpression)
//         */
//        public void visit( CaseExpression caseExpression ) {
//        }
//
//        /*
//         * (non-Javadoc)
//         *
//         * @see
//         * net.sf.jsqlparser.expression.ExpressionVisitor#visit(net.sf.jsqlparser
//         * .expression.WhenClause)
//         */
//        public void visit( WhenClause whenClause ) {
//        }
//
//        public void visit( AllComparisonExpression allComparisonExpression ) {
//            allComparisonExpression.GetSubSelect().getSelectBody().accept( this );
//        }
//
//        public void visit( AnyComparisonExpression anyComparisonExpression ) {
//            anyComparisonExpression.GetSubSelect().getSelectBody().accept( this );
//        }
//
//        public void visit( SubJoin subjoin ) {
//            subjoin.getLeft().accept( this );
//            subjoin.getJoin().getRightItem().accept( this );
//        }
//
//        public void visit( Concat concat ) {
//            visitBinaryExpression( concat );
//        }
//
//        public void visit( Matches matches ) {
//            visitBinaryExpression( matches );
//
//        }
//
//        public void visit( BitwiseAnd bitwiseAnd ) {
//            visitBinaryExpression( bitwiseAnd );
//
//        }
//
//        public void visit( BitwiseOr bitwiseOr ) {
//            visitBinaryExpression( bitwiseOr );
//
//        }
//
//        public void visit( BitwiseXor bitwiseXor ) {
//            visitBinaryExpression( bitwiseXor );
//        }
//
//        public void visit( StringValue stringValue ) {
//        }
//    }

}
